package com.hursing.tractor.model;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;

/**
 * 牌型。 单牌、对牌、三张、四张、拖拉机。
 */
public final class CardPattern {

	private LinkedList<Card> mSingles = new LinkedList<Card>();
	private LinkedList<LinkedList<Card>> mPairs = new LinkedList<LinkedList<Card>>();
	private LinkedList<LinkedList<LinkedList<Card>>> mTractors = new LinkedList<LinkedList<LinkedList<Card>>>();
	private LinkedList<Card> mCards = new LinkedList<Card>();
	private boolean mNoRepeat;

	public CardPattern(List<Card> cards, boolean noRepeat) {
		mCards.addAll(cards);
		mNoRepeat = noRepeat;
		calculatePattern();
	}

	public CardPattern(List<Card> cards) {
		this(cards, true);
	}

	private void calculatePattern() {
		mSingles.clear();
		mPairs.clear();
		mTractors.clear();
		if (mCards.size() == 1) {
			mSingles.add(mCards.getFirst());
			return;
		}
		// 先找出对牌
		boolean skip = false;
		for (int i = 1; i < mCards.size(); i++) {
			Card card = mCards.get(i);
			Card previous = mCards.get(i - 1);
			// 如果相同，则把前面的和现在的一起成对加入对牌。如果不同，把前面的加入单牌。如果已是最后一张还不同，则也加入单牌
			if (card.equals(previous)) {
				if (card.number() == GameData.instance().getCurrentMaster() && card.suit() != GameData.instance().getFlippedSuit()) {
					if (!skip) {
						skip = true;
						LinkedList<Card> pair = new LinkedList<Card>();
						pair.add(card);
						pair.add(card);
						mPairs.add(pair);
					}
				} else {
					LinkedList<Card> pair = new LinkedList<Card>();
					pair.add(card);
					pair.add(card);
					mPairs.add(pair);
				}
				
				if (i == mCards.size() - 2) {
					mSingles.add(mCards.get(i + 1));
					break;
				} else {
					i++;
				}
			} else {
				mSingles.add(previous);
				if (i == mCards.size() - 1) {
					mSingles.add(card);
					break;
				}
			}
		}
		LinkedList<LinkedList<Card>> pairs = mPairs;
		if (mNoRepeat) {
			pairs = new LinkedList<LinkedList<Card>>(mPairs);
		}
		// 找出连续的对牌即拖拉机
		for (int i = 0; i < pairs.size();) {
			LinkedList<Card> first = pairs.get(i);
			int j = i + 1;
			LinkedList<LinkedList<Card>> tractor = null;
			// 一直向后扫描
			while (j < pairs.size()) {
				LinkedList<Card> current = pairs.get(j);
				if (current.getFirst().suitDistinguishTrump() != first
						.getFirst().suitDistinguishTrump()) {
					break;
				}
				if (current.getFirst().height() - first.getFirst().height() != i - j) {
					break;
				}
				j++;
				if (tractor == null) {
					tractor = new LinkedList<LinkedList<Card>>();
					tractor.add(first);
					if (mNoRepeat) {
						mPairs.remove(first);
					}
				}
				tractor.add(current);
				if (mNoRepeat) {
					mPairs.remove(current);
				}
			}
			if (tractor != null) {
				mTractors.add(tractor);
			}
			i = j;
		}
		// 冒泡按牌数从多到少排序拖拉机
		for (int i = 0; i < mTractors.size(); i++) {
			for (int j = i + 1; j < mTractors.size(); j++) {
				LinkedList<LinkedList<Card>> iTractor = mTractors.get(i);
				LinkedList<LinkedList<Card>> jTractor = mTractors.get(j);
				int iSize = iTractor.getFirst().size() * iTractor.size();
				int jSize = jTractor.getFirst().size() * jTractor.size();
				if (jSize > iSize) {
					mTractors.set(i, jTractor);
					mTractors.set(j, iTractor);
				}
			}
		}
	}
	
	public LinkedList<Card> cards() {
		return mCards;
	}

	public LinkedList<Card> singles() {
		return mSingles;
	}

	public LinkedList<LinkedList<Card>> pairs() {
		return mPairs;
	}

	public LinkedList<LinkedList<LinkedList<Card>>> tractors() {
		return mTractors;
	}

	public List<Card> tractorCards(int index) {
		LinkedList<LinkedList<Card>> tractor = mTractors.get(index);
		ArrayList<Card> cards = new ArrayList<Card>(tractor.getFirst().size()
				* tractor.size());
		for (int i = 0; i < tractor.size(); i++) {
			cards.addAll(tractor.get(i));
		}
		return cards;
	}
	
	public boolean isSamePattern(CardPattern compare) {
		if (this.tractors().size() != compare.tractors().size()
				|| this.pairs().size() != compare.pairs().size()
				|| this.singles().size() != this.singles().size()) {
			return false;
		}
		if (this.tractors().size() != 0) {
			for (int i = 0; i < this.tractors().size(); i++) {
				List<Card> myTractor = this.tractorCards(i);
				List<Card> theirTractor = compare.tractorCards(i);
				if (myTractor.size() != theirTractor.size()) {
					return false;
				}
			}
		}
		return true;
	}

	public boolean isLargerThanCurrentLargest(CardPattern largest) {
		boolean isSameSuit = true;
		for (int i = 1; i < mCards.size(); i++) {
			Card card = mCards.get(i);
			Card previous = mCards.get(i - 1);
			// 在此循环中一同判断是否同花
			isSameSuit &= card.suitDistinguishTrump() == previous
					.suitDistinguishTrump();
		}
		if (!isSameSuit) {
			return false;
		}
		// 牌型一致的判断：拖拉机数和牌数、对牌数相等（如果前面相等，单牌数肯定相等）
		// 拖拉机数要不小于
		if (largest.tractors().size() > this.tractors().size()) {
			return false;
		}
		if (largest.tractors().size() != 0) {
			// 拖拉机最大的牌要大于
			if (!this
					.tractors()
					.getFirst()
					.getFirst()
					.getFirst()
					.isLargerThanOther(
							largest.tractors().getFirst().getFirst().getFirst())) {
				return false;
			}
			// 如果拖拉机牌数不等
			for (int i = 0; i < largest.tractors().size(); i++) {
				if (largest.tractorCards(i).size() > this.tractorCards(i)
						.size()) {
					return false;
				}
			}
		}
		//
		if (largest.pairs().size() > this.pairs().size()) {
			return false;
		}
		//
		if (largest.pairs().size() != 0) {
			return this
					.pairs()
					.getFirst()
					.getFirst()
					.isLargerThanOther(
							largest.pairs().getFirst().getFirst());
		}
		
		return this.mCards.getFirst().isLargerThanOther(largest.mCards.getFirst());
	}
	
	public LinkedList<Card> rejectThrow(CardPattern throwPattern) {
		LinkedList<Card> reject = new LinkedList<Card>();
		if (mCards.size() == 0) {
			return reject;
		}
		if (throwPattern.singles().size() > 0 && this.singles().size() > 0) {
			if (this.singles().getFirst().isLargerThanOther(throwPattern.singles().getLast())) {
				reject.add(throwPattern.singles().getLast());
				return reject;
			}
		}
		if (throwPattern.pairs().size() > 0 && this.pairs().size() > 0) {
			if (this.pairs().getFirst().getFirst().isLargerThanOther(throwPattern.pairs().getLast().getFirst())) {
				reject.addAll(throwPattern.pairs().getLast());
				return reject;
			}
		}
		if (throwPattern.tractors().size() > 0 && this.tractors().size() > 0) {
			List<Card> throwTractor = throwPattern.tractorCards(throwPattern.tractors().size() - 1);
			List<Card> myTractor = this.tractorCards(0);
			if (throwTractor.size() <= myTractor.size()) {
				Card throwCard = throwTractor.get(throwTractor.size() - 1);
				Card myCard = myTractor.get(0);
				if (myCard.isLargerThanOther(throwCard)) {
					reject.addAll(throwTractor);
				}
			}
		}
		return reject;
	}

	public void remove(Card card) {
		mCards.remove(card);
		calculatePattern();
	}

	public void remove(List<Card> cards) {
		ListIterator<Card> itor = cards.listIterator();
		while (itor.hasNext()) {
			mCards.remove(itor.next());
		}
		calculatePattern();
	}

	public void remove(LinkedList<LinkedList<Card>> cards) {
		ListIterator<LinkedList<Card>> itor = cards.listIterator();
		while (itor.hasNext()) {
			mCards.removeAll(itor.next());
		}
		calculatePattern();
	}
	
	public boolean isThrow() {
		int count = mTractors.size() + mPairs.size() + mSingles.size();
		return count != 1;
	}
}
